home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / Snippets / QuickDraw / Restore Screen Cluts / MenuHandler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-18  |  12.8 KB  |  419 lines  |  [TEXT/MPS ]

  1. /******************************************************************************\
  2. *
  3. * Apple Macintosh Developer Technical Support
  4. *
  5. * Menu-handling routines
  6. *
  7. * Program: ColorReset
  8. * File:    MenuHandler.c
  9. *
  10. * by:      Forrest Tanaka
  11. *
  12. * Copyright © 1988-1992 Apple Computer, Inc.
  13. * All rights reserved.
  14. *
  15. \******************************************************************************/
  16.  
  17.  
  18. /******************************************************************************\
  19. * Header Files
  20. \******************************************************************************/
  21.  
  22. #ifndef THINK_C
  23. #include <Desk.h>
  24. #include <Errors.h>
  25. #include <Memory.h>
  26. #include <Menus.h>
  27. #include <Resources.h>
  28. #endif
  29.  
  30. #include "ColorReset.h"
  31. #include "MenuHandler.h"
  32. #include "PictDocument.h"
  33.  
  34.  
  35. /******************************************************************************\
  36. * Constants
  37. \******************************************************************************/
  38.  
  39. #define rMenuBar 128 /* Resource ID of this application’s MBAR resource */
  40.  
  41. #define kNumMenuGuides (mLastMenu - mApple + 1) /* Number of menu guide recs */
  42.  
  43.  
  44. /******************************************************************************\
  45. * Types
  46. \******************************************************************************/
  47.  
  48. typedef struct
  49. {
  50.     MenuHandle theMenu; /* Handle to this guide’s menu */
  51.     long       enables; /* Current enable flags */
  52. } MenuGuide;
  53.  
  54.  
  55. /******************************************************************************\
  56. * Prototypes
  57. \******************************************************************************/
  58.  
  59. void DoAppleMenu(
  60.     short menuItem);
  61.  
  62. void DoFileMenu(
  63.     short menuItem);
  64.  
  65. void DoEditMenu(
  66.     short menuItem);
  67.  
  68. void DoDisplayMenu(
  69.     short menuItem);
  70.  
  71. void ResetMenuItems(void);
  72.  
  73. void FixDAMenus(void);
  74.  
  75.  
  76. /******************************************************************************\
  77. * Variables
  78. \******************************************************************************/
  79.  
  80. MenuGuide gMenuGuides[kNumMenuGuides]; /* Application’s menu guide records */
  81.  
  82.  
  83. /******************************************************************************\
  84. * Public: StartMenus
  85. *
  86. * The menu guide array is initialized with the menu handles and enable flags of
  87. * all menus.
  88. *
  89. * If GetNewMBar couldn’t load the MBAR resource, then it returns nil and the
  90. * error code is in ResError, and I can deal with the error elegantly.  But, if
  91. * the GetNewMBar couldn’t load the menus themselves, then it’ll probably crash.
  92. \******************************************************************************/
  93.  
  94. OSErr StartMenus()
  95. {
  96.     Handle menuBar;   /* Handle to the menu bar from the MBAR resource */
  97.     short  menuIndex; /* Index into menu guide records */
  98.     OSErr  error;
  99.  
  100.     /* Load in the menu bar */
  101.     menuBar = GetNewMBar( rMenuBar );
  102.     if (menuBar != nil)
  103.     {
  104.         /* Set it, then dispose of it because SetMenuBar makes a copy */
  105.         SetMenuBar( menuBar );
  106.         DisposHandle( menuBar );
  107.  
  108.         /* Add the desk accessories to the Apple menu */
  109.         AddResMenu( GetMHandle( mApple ), 'DRVR' );
  110.  
  111.         /* Initialize the menu guide array */
  112.         for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++)
  113.         {
  114.             gMenuGuides[menuIndex].theMenu = GetMHandle( menuIndex + mApple );
  115.             gMenuGuides[menuIndex].enables = (**gMenuGuides[menuIndex].
  116.                     theMenu).enableFlags;
  117.         }
  118.  
  119.         /* Draw the menu bar */
  120.         DrawMenuBar();
  121.         error = noErr;
  122.     }
  123.     else
  124.     {
  125.         error = ResError();
  126.         if (error == noErr)
  127.             error = resNotFound;
  128.         if (error != resNotFound && error != memFullErr)
  129.             error = dsSysErr;
  130.     }
  131.     return error;
  132. }
  133.  
  134.  
  135. /******************************************************************************\
  136. * Public: DoMenuChoice
  137. *
  138. * This routine should be self-explanatory.
  139. \******************************************************************************/
  140.  
  141. void DoMenuChoice(
  142.     long menuChoice) /* Return value from MenuSelect or MenuKey */
  143. {
  144.     short menuNum;  /* Menu number of chosen menu */
  145.     short menuItem; /* Item number of chosen menu item */
  146.  
  147.     if (menuChoice != 0)
  148.     {
  149.         /* Get the chosen menu item and menu number */
  150.         menuNum = hiWord( menuChoice );
  151.         menuItem = loWord( menuChoice );
  152.  
  153.         /* Dispatch the appropriate menu-handling routine */
  154.         if (menuNum == mApple)
  155.             DoAppleMenu( menuItem );
  156.         else if (menuNum == mFile)
  157.             DoFileMenu( menuItem );
  158.         else if (menuNum == mEdit)
  159.             DoEditMenu( menuItem );
  160.         else if (menuNum == mDisplay)
  161.             DoDisplayMenu( menuItem );
  162.         HiliteMenu( 0 );
  163.     }
  164. }
  165.  
  166.  
  167. /******************************************************************************\
  168. * Private: DoAppleMenu - Handle an Apple menu item choice
  169. *
  170. * This routine is called whenever it’s determined that the chosen menu item was
  171. * in the Apple menu.  If the chosen menu item that’s passed in the menuItem
  172. * parameter wasn’t the About item, the name of the menu item is retrieved and
  173. * then OpenDeskAcc is called with this name so that the desk accessory by that
  174. * name is opened.  The Process Manager can launch desk accessories, but
  175. * OpenDeskAcc should still be used if the user chooses any item in the Apple
  176. * menu.
  177. \******************************************************************************/
  178.  
  179. static void DoAppleMenu(
  180.     short menuItem) /* Chosen menu item */
  181. {
  182.     Str255 daName; /* Name of the chosen DA */
  183.     short  refNum; /* Reference number of the DA, ignored */
  184.  
  185.     if (menuItem != iAbout)
  186.     {
  187.         GetItem( GetMHandle( mApple ), menuItem, /*<*/daName );
  188.         refNum = OpenDeskAcc( daName );
  189.     }
  190. }
  191.  
  192.  
  193. /******************************************************************************\
  194. * Private: DoFileMenu - Handle a File menu item choice
  195. *
  196. * This routine is called whenever it’s determined that the chosen menu item was
  197. * in the File menu.  The item number of the chosen menu item is passed in the
  198. * menuItem parameter.
  199. \******************************************************************************/
  200.  
  201. static void DoFileMenu(
  202.     short menuItem) /* Chosen menu item */
  203. {
  204.     if (menuItem == iOpen)
  205.         (void)DoOpenPictDoc();
  206.     else if (menuItem == iClose)
  207.     {
  208.         if (IsPictDocWindow( FrontWindow() ))
  209.             DoClosePictDoc( FrontWindow() );
  210.     }
  211.     else if (menuItem == iSaveAs)
  212.     {
  213.         if (IsPictDocWindow( FrontWindow() ))
  214.             DoSaveAsPictDoc( FrontWindow() );
  215.     }
  216.     else if (menuItem == iQuit)
  217.         DoQuit();
  218. }
  219.  
  220.  
  221. /******************************************************************************\
  222. * Private: DoEditMenu - Handle a Edit menu item choice
  223. *
  224. * This routine is called whenever it’s determined that the chosen menu item was
  225. * in the Edit menu.  The item number of the chosen menu item is passed in the
  226. * menuItem parameter.
  227. \******************************************************************************/
  228.  
  229. static void DoEditMenu(
  230.     short menuItem) /* Chosen menu item */
  231. {
  232.     SystemEdit( menuItem - 1 );
  233. }
  234.  
  235.  
  236. /******************************************************************************\
  237. * Private: DoEditMenu - Handle a Edit menu item choice
  238. *
  239. * This routine is called whenever it’s determined that the chosen menu item was
  240. * in the Edit menu.  The item number of the chosen menu item is passed in the
  241. * menuItem parameter.
  242. \******************************************************************************/
  243.  
  244. static void DoDisplayMenu(
  245.     short menuItem) /* Chosen menu item */
  246. {
  247.     if (menuItem == 1)
  248.         RestoreColorsPalette();
  249.     else if (menuItem == 2)
  250.         RestoreColorsSlam();
  251. }
  252.  
  253.  
  254. /******************************************************************************\
  255. * Public: FixMenus
  256. *
  257. * FixMenus first disables every available menu item.  Then the most basic menu
  258. * items are enabled.  The windowKind field of the front window is then checked.
  259. * If there is a window open, FixMenus calls a routine that’s responsible for
  260. * that kind of window to enable any menu items that are relevant to that kind of
  261. * window.
  262. *
  263. * If the front window is a modal dialog, then the basic set of menu items are
  264. * ! enabled, and the entire Apple menu is disabled.
  265. *
  266. * After this is done, the menu bar might have to be redrawn to reflect the new
  267. * conditions.  So, FixMenus go through every menu to determine if the state of
  268. * the entire menu has changed.  The MenuGuide records are used to help determine
  269. * this.  If the state of any many has changed, then the menu bar is redrawn.
  270. \******************************************************************************/
  271.  
  272. void FixMenus()
  273. {
  274.     WindowPtr  currWindow; /* Pointer to the front-most window */
  275.     MenuHandle aMenu;      /* Handle to menu being enabled */
  276.     long       oldEnables; /* True if 1+ items enabled when FixMenus called */
  277.     long       newEnables; /* True if 1+ items enabled after menus fixed */
  278.     Boolean    mustRedraw; /* True if menu bar has to be redrawn */
  279.     short      numItems;   /* Number of items in a menu */
  280.     short      menuIndex;  /* Index into menu guide array */
  281.  
  282.     /* Start by disabling all menus */
  283.     ResetMenuItems();
  284.  
  285.     /* Front-most window determines most menu enabling/disabling */
  286.     currWindow = FrontWindow();
  287.  
  288.     /* Depending on the type of the front window, enable appropriate items */
  289.     if (IsDAWindow( currWindow ))
  290.         FixDAMenus();
  291.     else if (IsPictDocWindow( currWindow ))
  292.         FixPictDocMenus( currWindow );
  293.  
  294.     /* Enable some menus */
  295.     aMenu = GetMHandle( mFile );
  296.     EnableItem( aMenu, iOpen );
  297.  
  298.     /* Assume we don’t have to redraw the menu bar */
  299.     mustRedraw = false;
  300.  
  301.     /* Check through every menu to see if there are any enabled items in it */
  302.     for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++)
  303.     {
  304.         /* Grab the old and new enable flags excluding flag for entire menu */
  305.         oldEnables = gMenuGuides[menuIndex].enables & 0xFFFFFFFE;
  306.         newEnables = (**gMenuGuides[menuIndex].theMenu).enableFlags &
  307.                 0xFFFFFFFE;
  308.  
  309.         /* Shift left so that we only see flags for existing items */
  310.         numItems = CountMItems(gMenuGuides [menuIndex].theMenu);
  311.         oldEnables = oldEnables << (31 - numItems);
  312.         newEnables = newEnables << (31 - numItems);
  313.  
  314.         /* Determine if the menu bar must be redrawn */
  315.         if (((oldEnables != 0) && (newEnables == 0)) || numItems == 0)
  316.         {
  317.             /* Had some items enabled, now has no items enabled, redraw */
  318.             DisableItem( gMenuGuides[menuIndex].theMenu, 0 );
  319.             mustRedraw = true;
  320.         }
  321.         else if ((oldEnables == 0) && (newEnables != 0))
  322.         {
  323.             /* Had no items enabled, now has some items enabled, redraw */
  324.             EnableItem( gMenuGuides[menuIndex].theMenu, 0) ;
  325.             mustRedraw = true;
  326.         }
  327.  
  328.         /* Update our copy of the enable flags */
  329.         gMenuGuides[menuIndex].enables = (**gMenuGuides[menuIndex].theMenu).
  330.                 enableFlags;
  331.     }
  332.  
  333.     /* If at least one menu has changed state, must redraw the menu bar */
  334.     if (mustRedraw)
  335.         DrawMenuBar();
  336. }
  337.  
  338.  
  339. /******************************************************************************\
  340. * Private: ResetMenuItems - Disable any disableable items and clear marks
  341. *
  342. * Disabling all the menu items is done bruteforcedly.  It could easily be done
  343. * by looping through each menu and disabling every item that comes up (disabling
  344. * the Font menu is done this way), but I thought doing it using the brute-force
  345. * method was clearer.  Then again. . .
  346. \******************************************************************************/
  347.  
  348. static void ResetMenuItems ()
  349. {
  350.     MenuHandle aMenu; /* Handle to each menu we’re disabling */
  351.  
  352.     /* Disable items in the File menu */
  353.     aMenu = GetMHandle( mFile );
  354.     DisableItem( aMenu, iOpen );
  355.     DisableItem( aMenu, iClose );
  356.     DisableItem( aMenu, iSaveAs );
  357.  
  358.     /* Disable items in the Edit menu */
  359.     aMenu = GetMHandle( mEdit );
  360.     DisableItem( aMenu, iUndo );
  361.     DisableItem( aMenu, iCut );
  362.     DisableItem( aMenu, iCopy );
  363.     DisableItem( aMenu, iPaste );
  364.     DisableItem( aMenu, iClear );
  365. }
  366.  
  367.  
  368. /******************************************************************************\
  369. * Private: FixDAMenus - Enable any menu items relevant for desk accessories
  370. *
  371. * Desk accessories can use the Edit menu, so the standard Edit menu items are
  372. * enabled.
  373. \******************************************************************************/
  374.  
  375. static void FixDAMenus()
  376. {
  377.     MenuHandle aMenu; /* Handle to each menu we’re enabling */
  378.  
  379.     /* Disable items in the Process menu */
  380.     aMenu = GetMHandle( mEdit );
  381.     EnableItem( aMenu, iUndo );
  382.     EnableItem( aMenu, iCut );
  383.     EnableItem( aMenu, iCopy );
  384.     EnableItem( aMenu, iPaste );
  385.     EnableItem( aMenu, iClear );
  386. }
  387.  
  388.  
  389. /******************************************************************************\
  390. * Public: DisableAllMenus
  391. *
  392. \******************************************************************************/
  393.  
  394. void DisableAllMenus()
  395. {
  396.     short menuIndex; /* Index into menu guide array */
  397.  
  398.     /* Check through every menu to see if there are any enabled items in it */
  399.     for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++)
  400.         DisableItem( gMenuGuides[menuIndex].theMenu, 0 );
  401. }
  402.  
  403. /******************************************************************************\
  404. * Public: RestoreAllMenus
  405. *
  406. \******************************************************************************/
  407.  
  408. void ReenableAllMenus()
  409. {
  410.     short menuIndex; /* Index into menu guide array */
  411.  
  412.     /* Check through every menu to see if there are any enabled items in it */
  413.     for (menuIndex = 0; menuIndex < kNumMenuGuides; menuIndex++)
  414.         if ( gMenuGuides[menuIndex].enables & 1 )
  415.             EnableItem( gMenuGuides[menuIndex].theMenu, 0 );
  416. }
  417.